import express from 'express'
import { Response, Request } from "express"

const router = express.Router()

import { success, failure } from '../utils/responses'
import * as fs from "node:fs";
import axios from "axios";
import { parseExcel } from "../utils/excel";
import { AppDataSource } from "../config/database";
import { FindManyOptions } from "typeorm";
import { Exam } from "../entities/Exam";
import { AuthRequest } from "../middlewares/user-auth";
import { NotFound } from "http-errors";

interface ExamResponse {
  questionIndex: number
  questionType: string
  questionTitle: string
  questionOptions: string | string[]
  questionCorrectAnswer: string
  questionScore: number
  questionAnalysis: string
}

/**
 * 获取解析后的题库数据
 */
router.get('/', async function (req: Request, res: Response) {
  try {
    const examUrl = req.query.examUrl as string

    // 获取对应数据库中存入记录的id
    const examRepository = AppDataSource.getRepository(Exam)

    console.log('地址：' + examUrl)
    const examInstance = await examRepository.findOneBy({ downloadUrl: examUrl })
    if (!examInstance) throw new NotFound('没找到上传的试卷')

    let front = (examUrl as string).split('?')[0] // 截取?前一半地址
    const filename = front.substring(front.lastIndexOf('/') + 1) + '.xlsx'
    const response = await axios.get(examUrl, {
      responseType: 'stream',
    })

    // 创建一个写入流
    const writer = fs.createWriteStream(filename)
    response.data.pipe(writer)
    writer.on('finish', async () => {
      console.log('文件写入完成');
      // 解析Excel文件
      const exam = await parseExcel(filename) as ExamResponse[]
      // 计算总分
      const totalScore = exam.slice(1).reduce((prev, cur) => prev + cur.questionScore, 0)
      // 别忘了删除本地临时Excel文件
      fs.unlinkSync(filename)
      success(res, '解析题库成功', {
        paper: {
          id: examInstance.id,
          title: examInstance.title,
          description: examInstance.description,
          createdAt: examInstance.createdAt,
          isDone: examInstance.isDone,
          totalScore
        },
        exam
      })
    })
  } catch (error) {
    failure(res, error)
  }
})

/**
 * 获取用户题库列表
 */
router.get('/list', async function (req: Request, res: Response) {
  try {
    const query = req.query

    const currentPage = Math.abs(Number(query.currentPage)) || 1 // 当前页
    const pageSize = Math.abs(Number(query.pageSize)) || 10 // 每页条数
    const offset = (currentPage - 1) * pageSize // 偏移量

    const examRepository = AppDataSource.getRepository(Exam)

    const findOptions: FindManyOptions = {
      where: {
        writerId: (req as AuthRequest).id, // 筛选做题对象是当前用户的题库
      },
      relations: {
        author: true,
      },
      skip: offset,
      take: pageSize,
      order: {
        isDone: 'ASC',
        createdAt: 'DESC'
      }
    }

    const [exams, totalCount] = await examRepository.findAndCount(findOptions)

    // 去除不需要的字段
    const filterExams = exams.map(exam => {
      const { id, title, description, isDone, createdAt, author } = exam;
      return {
        id,
        title,
        createdAt,
        description,
        isDone,
        author: {
          id: author.id,
          username: author.username,
        }
      }
    })

    success(res, '获取题库列表成功', {
      exams: filterExams,
      pagination: {
        totalPage: Math.ceil(totalCount / pageSize),
        currentPage,
        pageSize,
        totalCount
      }
    })
  } catch (error) {
    failure(res, error)
  }
})

/**
 * 根据试卷id获取试卷和题目
 */
router.get('/:examId', async function (req: Request, res: Response) {
  try {
    const examId = Number(req.params.examId)

    // 获取对应数据库中存入记录的id
    const examRepository = AppDataSource.getRepository(Exam)

    const examInstance = await examRepository.findOneBy({ id: examId })
    if (!examInstance) throw new NotFound('没找到上传的试卷')

    const examUrl = examInstance.downloadUrl
    let front = (examUrl as string).split('?')[0] // 截取?前一半地址
    const filename = front.substring(front.lastIndexOf('/') + 1) + '.xlsx'
    const response = await axios.get(examUrl, {
      responseType: 'stream',
    })

    // 创建一个写入流
    const writer = fs.createWriteStream(filename)
    response.data.pipe(writer)
    writer.on('finish', async () => {
      console.log('文件写入完成');
      // 解析Excel文件
      const exam = await parseExcel(filename)
      // 别忘了删除本地临时Excel文件
      fs.unlinkSync(filename)
      success(res, '获取试卷和题目成功', {
        paper: {
          id: examInstance.id,
          title: examInstance.title,
          description: examInstance.description,
          createdAt: examInstance.createdAt,
          isDone: examInstance.isDone,
          totalScore: exam.slice(1).reduce((prev, cur) => prev + cur.questionScore, 0)
        },
        exam
      })
    })
  } catch (error) {
    failure(res, error)
  }
})

/**
 * 更新用户完成试卷状态
 */
router.post('/', async function (req: Request, res: Response) {
  try {
    const { examId, isDone } = req.body

    // 获取对应数据库中存入记录的id
    const examRepository = AppDataSource.getRepository(Exam)
    const examInstance = await examRepository.findOneBy({ id: examId })
    if (!examInstance) throw new NotFound('没找到上传的试卷')

    examInstance.isDone = isDone // 更新试卷完成状态
    await examRepository.save(examInstance)
    success(res, '更新用户完成试卷状态成功')
  } catch (error) {
    failure(res, error)
  }
})

export default router
